﻿using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using TicketMLib;
using AreaStructManipulators;
using System.Web;
using System.Data;

namespace TicketMRouting
{
    public class Router
    {
        private AreaStructMan A_Man;
        private static string RoutingConfigPath;
        public Router()
        {
            A_Man = new AreaStructMan();
            RoutingConfigPath = "/App_Data/AreasStruct.xml";
        }
        #region Routing

        /// <summary>
        /// This is a method in which the assignment constraints as set in ticket work item for selected project are read and stored in the AreasStruct.xml file
        /// </summary>
        /// <param name="docParam">This parameter is the current area structure read in GetAreaStructure method is passed on</param>
        /// <param name="sProject"></param>
        public void GetRoutingConditions(XmlDocument docParam, string sProject)
        {
            try
            {
                //The parameter docParam is the Area Structure of the selected project.
                #region Get Variable Values from existing config file
                string uName;
                string passwd;
                string domain;
                string tfs;
                string collection;
                string _project;
                Utils.SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
                #endregion
                //Connect to TFS
                TfsTeamProjectCollection tpc = Utils.Connect2Tfs(uName, passwd, domain, tfs, collection);
                var wiStore = tpc.GetService<WorkItemStore>();
                var project = wiStore.Projects[_project];
                //Get the existing definition of Ticket WITD
                WorkItemType wiType = project.WorkItemTypes["Ticket"];
                //Export the Ticket WITD in a XML Document structure
                XmlDocument doc1 = wiType.Export(true);
                XmlNode root1 = doc1.DocumentElement;
                //Get the node for 'Assgined To' Field
                XmlNode node = root1.SelectSingleNode("//FIELDS/FIELD[@name='Assigned To']");


                int ctr = 0;
                //Get all nodes for Area from AreasStruct.xml file
                XmlNodeList areaNodes = docParam.FirstChild.NextSibling.SelectNodes("/*/*");
                //Read each area node    
                while (ctr < areaNodes.Count)
                {
                    string areaPath = areaNodes[ctr].Attributes["Name"].Value.ToString();
                    //Get Area Id for each area node        
                    int areaId = A_Man.GetAreaId(areaPath, _project);
                    XmlNode defaultAssigneeNode = docParam.CreateNode(XmlNodeType.Element, "Assignee", null);
                    if (node.SelectSingleNode("WHEN[@value='" + areaId + "']/*/*") != null)
                    {
                        defaultAssigneeNode.InnerText = node.SelectSingleNode("WHEN[@value='" + areaId + "']/*/*").Attributes["value"].Value.ToString();

                        XmlNode root = docParam.DocumentElement;
                        XmlNode targetAreaNode = root.SelectSingleNode("/Project/SubArea[@Name='" + areaPath + "']");
                        targetAreaNode.AppendChild(defaultAssigneeNode);
                    }
                    ctr++;
                }
                docParam.Save(HttpContext.Current.Server.MapPath(RoutingConfigPath));
            }
            catch
            {

                throw;
            }

        }
        /// <summary>
        /// This method reads existing routing data from the configuration file AreasStruct.xml and converts it to a datatable.
        /// That datatable is bound to the datagrid on the Routing.aspx
        /// </summary>
        /// <param name="sProject">Session variable that represents selected project</param>
        /// <returns></returns>
        public DataTable ReadRoutingFromTFS(string sProject)
        {
            DataTable RoutingTable = new DataTable("RoutingTable");
            RoutingTable.Columns.Add("AreaPath", typeof(string));
            RoutingTable.Columns.Add("AssignedTo", typeof(string));

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(HttpContext.Current.Server.MapPath(RoutingConfigPath));
                XmlNode ProjectNode = doc.DocumentElement.SelectSingleNode("/Project[@Name='" + sProject + "']");
                if (ProjectNode.HasChildNodes)
                {
                    XmlNodeList RoutingList = ProjectNode.ChildNodes;
                    foreach (XmlNode subarea in RoutingList)
                    {
                        DataRow dRow = RoutingTable.NewRow();
                        dRow["AreaPath"] = subarea.Attributes["Name"].Value.ToString();
                        if (subarea.HasChildNodes)
                            dRow["AssignedTo"] = subarea.FirstChild.InnerText;
                        else
                            dRow["AssignedTo"] = "";
                        RoutingTable.Rows.Add(dRow);
                    }
                }
            }
            catch
            {

                throw;
            }
            return RoutingTable;
        }
        public bool UpdateRouting(string sProject)
        {
            #region Get Variable Values from existing config file
            string uName;
            string passwd;
            string domain;
            string tfs;
            string collection;
            string _project;
            Utils.SetGenVarValues(sProject, out uName, out passwd, out domain, out tfs, out collection, out _project);
            #endregion

            #region Connect to TFS, get project name and Ticket Type

            TfsTeamProjectCollection tpc = Utils.Connect2Tfs(uName, passwd, domain, tfs, collection);
            var wiStore = tpc.GetService<WorkItemStore>();
            var project = wiStore.Projects[_project];
            WorkItemType wiType = project.WorkItemTypes["Ticket"];
            #endregion

            #region Read Area Structure from a local file and get AreaIds for each AreaPath
            XmlDocument tempDoc = new XmlDocument();
            tempDoc.Load(HttpContext.Current.Server.MapPath(RoutingConfigPath));
            XmlNode ProjectNode = tempDoc.DocumentElement.SelectSingleNode("/Project[@Name='" + _project + "']");


            XmlNodeList AllAreaPathNodes = ProjectNode.ChildNodes;

            List<int> areaIds = new List<int>();
            foreach (XmlNode areaPath in AllAreaPathNodes)
            {
                areaIds.Add(A_Man.GetAreaId(areaPath.Attributes["Name"].Value.ToString(), sProject));
            }
            #endregion

            #region Read Ticket type definition and get AssignedTo field with constraints
            XmlDocument doc1 = wiType.Export(true);
            XmlNode root1 = doc1.DocumentElement;
            XmlNode AssignedToNode = root1.SelectSingleNode("//FIELDS/FIELD[@name='Assigned To']");
            #endregion


            int ctr = 0;
            while (ctr < areaIds.Count)
            {
                XmlNode AssigneeNode = AssignedToNode.SelectSingleNode("WHEN[@value='" + areaIds[ctr] + "']/*/*");
                if (AssigneeNode != null)
                {
                    AssigneeNode.Attributes["value"].Value = AllAreaPathNodes[ctr].Attributes[0].Value;
                }
                else if (AllAreaPathNodes[ctr].InnerXml != "")
                {
                    XmlNode WhenNode = doc1.CreateNode(XmlNodeType.Element, "WHEN", null);
                    XmlAttribute fieldAttrib = doc1.CreateAttribute("field");
                    fieldAttrib.Value = "System.AreaId";
                    XmlAttribute valueAttrib = doc1.CreateAttribute("value");
                    valueAttrib.Value = areaIds[ctr].ToString();
                    WhenNode.Attributes.Append(fieldAttrib);
                    WhenNode.Attributes.Append(valueAttrib);

                    XmlNode AllowedValuesNode = doc1.CreateNode(XmlNodeType.Element, "ALLOWEDVALUES", null);
                    XmlAttribute expandAttrib = doc1.CreateAttribute("expanditems");
                    expandAttrib.Value = "true";
                    AllowedValuesNode.Attributes.Append(expandAttrib);

                    XmlNode ListItemNode = doc1.CreateNode(XmlNodeType.Element, "LISTITEM", null);
                    XmlAttribute valueAttrib2 = doc1.CreateAttribute("value");
                    valueAttrib2.Value = AllAreaPathNodes[ctr].FirstChild.InnerText;
                    ListItemNode.Attributes.Append(valueAttrib2);

                    AllowedValuesNode.AppendChild(ListItemNode);
                    WhenNode.AppendChild(AllowedValuesNode);
                    AssignedToNode.AppendChild(WhenNode);
                }
                ctr++;
            }
            project.WorkItemTypes.Import(doc1.InnerXml);
            return true;
        }
        #endregion
    }
}
